package com.lz.sports.bean

import android.os.Parcel
import android.os.Parcelable
import android.util.ArrayMap
import androidx.annotation.NonNull
import androidx.room.*
import com.lz.library.proguard.IProguardField

//设备组
@Entity(tableName = "DeviceGroup", indices = [Index("name")])
class DeviceGroup() : ParcelableString, IProguardField {

    companion object {

        //根据numbers类型的最大值
        const val MAX_NUMBER = 64

        //无效的序号
        const val INVALID_NUMBER = -1

        @JvmField
        val CREATOR = object : Parcelable.Creator<DeviceGroup> {
            override fun createFromParcel(parcel: Parcel): DeviceGroup {
                return DeviceGroup(parcel)
            }

            override fun newArray(size: Int): Array<DeviceGroup?> {
                return arrayOfNulls(size)
            }
        }
    }

    @Ignore
    constructor(projectId: Int, name: String) : this() {
        this.projectId = projectId
        this.name = name
    }

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    var id: Int = 0

    //所属项目ID
    @ColumnInfo(name = "projectId")
    var projectId: Int = 0

    @ColumnInfo(name = "name")
    @NonNull
    var name: String = ""

    //添加设备的序号  00000000 00000000
    @ColumnInfo(name = "numbers")
    var numbers: Long = 0L

    //组下的设备列表, mac键
    @Ignore
    private val deviceInfoMap = ArrayMap<String, DeviceInfo>()

    //对应number的序号
    @Ignore
    private val deviceInfoNumberMap = ArrayMap<Int, DeviceInfo>()

    //设备列表
    @Ignore
    private val deviceInfoList = ArrayList<DeviceInfo>()

    //设备列表
    fun deviceList(): List<DeviceInfo> = deviceInfoList

    //设备数量
    fun getDeviceCount(): Int = deviceInfoMap.size

    //是否未达标
    fun isLess(): Boolean = true

    //查询库初始化
    fun initDeviceInfoList(infoList: List<DeviceInfo>) {
        infoList.forEach {
            deviceInfoMap[it.mac] = it
            deviceInfoNumberMap[it.number] = it
            deviceInfoList.add(it)
        }
    }

    //查找设备
    fun findDeviceInfo(mac: String): DeviceInfo? = deviceInfoMap[mac]

    //通过序号找设备
    fun findDeviceInfo(number: Int): DeviceInfo? = deviceInfoNumberMap[number]

    //当前组自动生成序号
    private fun autoCreateNumber(): Int {
        for (i in 0 until MAX_NUMBER) {
            val num = numbers.shr(i).and(1)
            if (num == 0L) {
                numbers += 1L.shl(i)
                return i + 1
            }
        }
        return INVALID_NUMBER
    }

    //回收序号
    private fun recycleNumber(number: Int) {
        if (isNumberExist(number)) {
            numbers -= 1L.shl(number - 1)
        }
    }

    //该序号是否存在
    private fun isNumberExist(number: Int): Boolean {
        if (number in 1..MAX_NUMBER) {
            return numbers.shr(number - 1).and(1) == 1L
        }
        return false
    }

    //修改设备序号
    fun modifyDeviceInfoNumber(deviceInfo: DeviceInfo, newNumber: Int): Boolean {
        if (deviceInfo.number != newNumber && newNumber in 1..MAX_NUMBER
            && deviceInfoMap.contains(deviceInfo.mac) && !isNumberExist(newNumber)) {
            deviceInfoNumberMap.remove(deviceInfo.number)
            recycleNumber(deviceInfo.number)
            numbers += 1L.shl(newNumber - 1)
            deviceInfo.number = newNumber
            deviceInfoNumberMap[newNumber] = deviceInfo
            return true
        }
        return false
    }

    //解除绑定设备
    fun unbindDeviceInfo(deviceInfo: DeviceInfo): Boolean {
        val delete = deviceInfoMap.remove(deviceInfo.mac)
        if (delete != null) {
            deviceInfoNumberMap.remove(deviceInfo.number)
            recycleNumber(deviceInfo.number)
            deviceInfo.unbindGroup()
            deviceInfoList.remove(deviceInfo)
            return true
        }
        return false
    }

    //单独取消绑定设备序号
    fun recycleDeviceInfoNumber(number: Int) {
        recycleNumber(number)
    }

    //绑定设备
    fun bindDeviceInfo(deviceInfo: DeviceInfo): Int {
        if (!deviceInfoMap.contains(deviceInfo.mac)) {
            val number = autoCreateNumber()
            if (number != INVALID_NUMBER) {
                deviceInfo.bindGroup(id, number)
                deviceInfoMap[deviceInfo.mac] = deviceInfo
                deviceInfoNumberMap[number] = deviceInfo
                deviceInfoList.add(deviceInfo)
            }
            return number
        }
        return 0
    }

    fun clear() {
        deviceInfoMap.clear()
        deviceInfoList.clear()
        deviceInfoNumberMap.clear()
        numbers = 0L
    }

    //重置电量
    fun resetBattery() {
        deviceInfoList.forEach { it.resetBattery() }
    }

    override fun describeContents(): Int = 0

    @Suppress("DEPRECATION")
    constructor(parcel: Parcel) : this() {
        id = parcel.readInt()
        projectId = parcel.readInt()
        name = parcel.readString()!!

        parcel.readList(deviceInfoList, javaClass.classLoader)
        parcel.readMap(deviceInfoMap, javaClass.classLoader)
        parcel.readMap(deviceInfoNumberMap, javaClass.classLoader)
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(id)
        parcel.writeInt(projectId)
        parcel.writeString(name)
        parcel.writeList(deviceInfoList)
        parcel.writeMap(deviceInfoMap)
        parcel.writeMap(deviceInfoNumberMap)
    }

    override fun str(): String = name

    override fun equals(other: Any?): Boolean = other === this || (other is DeviceGroup && other.id == id)

    override fun toString(): String = name
}